#!/usr/bin/perl
#
# Write the info on Linux user IDs into the place entries.
# Reads through the Clean person database for its info.
#
use strict;

use FileTable;
use POSIX;
use Reportsub;
use Validate::Places;

use vars qw($maxentries $persons $placefile $key $recmax $linecount
 $emptycount $clearemptylists $rec $placeid %map %userlist $placeid
 $place $reccount $skipcount $savecount $clears);

# DIRTY HACK: Use info from FileTable module to get a reasonable
# size limit for the user list
# Calculate 6 bytes per user, and leave 2 Kbytes for the rest.
$maxentries = int(($FileTable::Record::MAXRECSIZE - 2000) / 6);

print STDERR "Max no. of users is $maxentries\n";
$placefile = FileTable::open("db/places", O_RDWR);
$persons = FileTable::open("db/persons");

while ($ARGV[0] =~ "^-") {
    my $opt = shift;
    if ($opt eq "-z") {
	$clearemptylists = 1;
	print STDERR "Zeroing placelists\n";
    } elsif ($opt eq "-t") {
	$recmax = shift;
	print STDERR "Test mode - $recmax records\n";
    }
} 
print STDERR "Reading records\n";
while ($key = $persons->each()) {
    ++ $linecount;
    print STDERR "$linecount\r" if $linecount % 100 == 0 && -t STDERR;
    last if $recmax && $linecount > $recmax; # test mode switch
    $rec = $persons->getclean($key);
    if (!$rec) {
	++ $emptycount;
	next;
    }
    $placeid = $rec->{placeid};
    if (!$map{$placeid}) {
	# Try to find a placeid for it
	$rec = $placefile->getbykey("name", $placeid);
	if (!$rec || $rec->{type} eq "alias") {
	    warn "$key: Person belongs to missing or alias - listed in xw\n";
	    $map{$placeid} = "XW";
	} else {
	    $map{$placeid} = $placeid;
	}
    }
    push(@{$userlist{$map{$placeid}}}, $key);
}

print STDERR "Saving user lists\n";
for $place (keys(%userlist)) {
    ++ $reccount;
    my $rec = $placefile->getbykey("name", $place);
    # sort to get canonical ordering, cut off too large lists
    my @list = sort {$a <=> $b} @{$userlist{$place}};
    if (@list > $maxentries) {
	$skipcount = @list - $maxentries;
	splice(@list, $maxentries); # make sure list isn't too long
    }
    my $cand = join(" ", @list);
    if ($rec) {
	if ($rec->{type} eq "alias") {
	    if ($cand) {
		warn "Error: $$rec{name} is an alias with users\n";
	    }
	    if ($rec->{userlist}) {
		warn "Deleting userlist from alias entry\n";
		delete $rec->{userlist};
		$rec->store();
	    }
	} elsif ($rec->{userlist} ne $cand) {
	    ++ $savecount;
	    print STDERR "Save ", $rec->{name}, "\n" if -t STDERR;
	    if ($recmax) {
		print "Test mode: Not Changing $place userlist to $cand\n";
	    } else {
		$rec->{userlist} = $cand;
		$rec->store('NOTEXT');
	    }
	}
    } else {
	print STDERR "No/empty record found for $place\n";
    }
}

# Remove all empty placelists
if ($clearemptylists) {
    print STDERR "Removing now-empty placelists\n";
    while ($place = $placefile->each()) {
	$rec = $placefile->get($place);
	my $name = $rec->{name};
	$name =~ tr/A-Z/a-z/;
	if ($rec->{userlist} 
	    && !$userlist{$name}) {
	    delete $rec->{userlist};
	    print STDERR "Clearing userlist $rec->{name}\n" if -t STDERR;
	    $rec->store();
	    ++ $clears;
	}
    }
}


print STDERR "$linecount records read from persons\n";
print STDERR "$reccount place records, $savecount modified\n";
print STDERR "$skipcount records skipped for space reasons\n";
print STDERR "$emptycount non-present records skipped\n";
print STDERR "$clears records cleared\n";
